const sRoot = __dirname;
const osFs = require("fs");
const osPath = require("path");
const {exec: osExec} = require('child_process');

// 导入规则表
const { oEslintReco, oEslintAdd, oPluginVue } = require('./rules-config.js');

let aDefScriptPath = { // 输入规则目录
  "eslint": "eslint-rules",
  "vue": "vue-rules"
}

const oDefOutFile = { // 输出文件名
  "eslint": "eslint-base.js",
  "vue": "vue-base.js",
};

const oOutPutTypePath = { // 输出目录
  "json": "./dist",
  "html": "../web/public/",
}

class ReadFile {
  constructor() {
    // 取目录列表
    this.aFileLst = [];
    // 缓存所有文件内容
    this.aFileContext = {};
    // 访问目录
    this.sDirPath = null;
  }
  set aList(aVal) {
    this.aFileLst = aVal;
  }
  set sDir(sVal) {
    this.sDirPath = sVal;
  }
  get oFileCon() {
    return this.aFileContext;
  }

  // 遍历文件列表加载缓存
  requireAll() {
    this.aFileLst.map((sItem) => {
      const sTempPath = osPath.join(sRoot, this.sDirPath, sItem);
      let oRequVal = require(sTempPath);
      this.aFileContext[oRequVal["name"]] = oRequVal;
    });
  }
}

// 写文档方法
const WriteFile = {
  sTplWarp: null,
  oAllCon: null,
  sType: null,

  cfg: function (sType) {
    const oTpl = {
      html: `export default values;`,
      json: `module.exports = values;`,
    };
    this.sType = sType;
    this.sTplWarp = oTpl[sType];
    return this;
  },
  mkdirSync: function (psDirName) {
    if (osFs.existsSync(psDirName)) {
      return true;
    } else {
      if (this.mkdirSync(osPath.dirname(psDirName))) {
        osFs.mkdirSync(psDirName);
        return true;
      }
    }
    return this;
  },
  setCon: function (oAllCon) {
    this.oAllCon = oAllCon;
    return this;
  },
  repalceVal: function (oVal, sOutPutType) {
    const sVal = JSON.stringify(oVal, null, sOutPutType);
    return this.sTplWarp.toString().replace(/values/, sVal);
  },
  output: function (sFileName, sOutPutType = "\t") {
    // 创建目录
    this.mkdirSync(osPath.parse(sFileName).dir);
    // 写文件
    osFs.writeFileSync(
      sFileName,
      this.repalceVal(this.oAllCon, sOutPutType),
      { flag: "w+" }
    );
  },
};

async function createZip(input, output) {
  const sVal = `zip -x "*.DS_Store" -j -r ${output} ${input}`;
  osExec(sVal, (error, stdout, stderr) => {
    if (error) {
      console.error(`执行的错误: ${error}`);
      return;
    }
    console.log(`stdout: ${stdout}`);
    console.error(`stderr: ${stderr}`);
  });
}


// get eslint rules
const newReadFile = new ReadFile();
newReadFile.sDir = aDefScriptPath['eslint'];
newReadFile.aList = [...Object.keys(oEslintReco), ...Object.keys(oEslintAdd)];
newReadFile.requireAll();
const oEslintCon = newReadFile.aFileContext;

// get vue rules
const newReadFileVue = new ReadFile();
newReadFileVue.sDir = aDefScriptPath['vue'];
const oNewVueRulesKeys = Object.keys(oPluginVue).map( (sItem) => { // 过滤掉 vue/
  return sItem.replace("vue/", "");
});
newReadFileVue.aList = oNewVueRulesKeys;
newReadFileVue.requireAll();
const oEslintVueCon = newReadFileVue.aFileContext;
// 合并规则
const oAllRules = {
  ...oEslintCon,
  ...oEslintVueCon
}
// 处理eslint输出内容
let oEslintRules = {};
const aKeyLst = Object.getOwnPropertyNames(oAllRules);
aKeyLst.map((item) => {
  const { name, value } = oAllRules[item];
  oEslintRules[name] = value;
});

// 取eslint外层模板
let oVueEslintrc = require("./tpl/eslintrc-vue.js");
oVueEslintrc["rules"] = {
  ...oVueEslintrc["rules"],
  ...oEslintRules,
};

WriteFile
  .cfg("json")
  .setCon(oVueEslintrc)
  .output(osPath.join(sRoot, oOutPutTypePath['json'], oDefOutFile['eslint']));

WriteFile
  .cfg("html")
  .setCon(oEslintCon)
  .output(osPath.join(sRoot, oOutPutTypePath['html'], oDefOutFile['eslint']), 0);

WriteFile
  .cfg("html")
  .setCon(oEslintVueCon)
  .output(osPath.join(sRoot, oOutPutTypePath['html'], oDefOutFile['vue']), 0);


createZip(
  osPath.join(sRoot, "dist", "eslint-base.js"), 
  "../web/public/eslintrc.js.zip"
);
